package log

import (
	"errors"
	"fmt"
	"log"
	"os"
	"strings"
	"time"
)

// loglevel
const (
	debuglevel   = 0
	releaselevel = 1
	errorlevel   = 2
	fatallevel   = 3
)

// levelmsg
const (
	debugmsg   = "[DEBUG] "
	releasemsg = "[RELEASE] "
	errormsg   = "[ERROR] "
	fatalmsg   = "[FATAL] "
)

type Logger struct {
	loglevel   int
	baselogger *log.Logger
	basefile   *os.File
}

func New(strlevel string, pathname string, flag int) (*Logger, error) {
	//根据字符串确定限制等级
	var level int
	switch strings.ToLower(strlevel) {
	case "debug":
		level = debuglevel
	case "realease":
		level = releaselevel
	case "error":
		level = errorlevel
	case "fatal":
		level = fatallevel
	default:
		return nil, errors.New("unknow level: " + strlevel) //错误处理
	}

	//组织内部结构
	//1.确定落地路径
	var basefile *os.File
	var baselogger *log.Logger
	if pathname != "" { //有指定落地目录
		//构建落地文件名
		time := time.Now()
		filename := fmt.Sprintf("%d%02d%02d-%02d:%02d:%02d.log",
			time.Year(), time.Month(), time.Day(), time.Hour(), time.Minute(), time.Second())

		file, err := os.Create(filename)
		if err != nil {
			return nil, err
		}
		basefile = file
		baselogger = log.New(file, "", flag)
	} else {
		baselogger = log.New(os.Stdout, "", flag)
	}

	//构建Logger对象
	logger := new(Logger)
	logger.loglevel = level
	logger.basefile = basefile
	logger.baselogger = baselogger

	return logger, nil
}

func (logger *Logger) Close() {
	if logger.basefile != nil {
		logger.basefile.Close()
	}
	logger.basefile = nil
	logger.baselogger = nil
}

func (logger *Logger) doprint(level int, levelmsg string, format string, args ...interface{}) {
	if level < logger.loglevel {
		return
	}

	if logger.baselogger == nil {
		panic("logger is closed")
	}

	format = levelmsg + format
	logger.baselogger.Output(3, fmt.Sprintf(format, args...))

	if level == fatallevel {
		os.Exit(1)
	}
}

func (logger *Logger) Debug(format string, args ...interface{}) {
	logger.doprint(debuglevel, debugmsg, format, args...)
}

func (logger *Logger) Release(format string, args ...interface{}) {
	logger.doprint(releaselevel, releasemsg, format, args...)
}

func (logger *Logger) Error(format string, args ...interface{}) {
	logger.doprint(errorlevel, errormsg, format, args...)
}

func (logger *Logger) Fatal(format string, args ...interface{}) {
	logger.doprint(fatallevel, fatalmsg, format, args...)
}

var gLogger, _ = New("debug", "", log.LstdFlags|log.Lshortfile)

func Export(logger *Logger) {
	if logger != nil {
		gLogger = logger
	}
}

func Debug(format string, args ...interface{}) {
	gLogger.doprint(debuglevel, debugmsg, format, args...)
}

func Release(format string, args ...interface{}) {
	gLogger.doprint(releaselevel, releasemsg, format, args...)
}

func Error(format string, args ...interface{}) {
	gLogger.doprint(errorlevel, errormsg, format, args...)
}

func Fatal(format string, args ...interface{}) {
	gLogger.doprint(fatallevel, fatalmsg, format, args...)
}

func Close() {
	gLogger.Close()
}
